/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ca.trader.user;

import ca.trader.enterprisebeans.UserBeanLocal;
import ca.trader.logger.TraderLogger;
import ca.trader.utils.DebugUtils;
import ca.trader.utils.HttpConsts;
import ca.trader.utils.HttpUtils;
import java.io.IOException;
import java.sql.SQLException;
import javax.ejb.EJB;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author Ahsan
 */
public class HttpUserRememberFilter implements Filter
{
	 private static final String _className = HttpUserRememberFilter.class.getName();

	 // The filter configuration object we are associated with.  If
	 // this value is null, this filter instance is not currently
	 // configured. 
	 private FilterConfig filterConfig = null;
	 @EJB
	 UserBeanLocal userBean;

	 public HttpUserRememberFilter()
	 {
	 }

	 private void doBeforeProcessing(ServletRequest req, ServletResponse res) throws IOException, ServletException, ClassNotFoundException, SQLException
	 {
		  String _methodName = "doBeforeProcessing";
		  
		  TraderLogger.init();

		  TraderLogger.logMethodEntry(_className, _methodName);


		  loginUserIfRemembered(req, res);


		  //Runtime.getRuntime().addShutdownHook(new ShutdownListener());


		  TraderLogger.logMethodExit(_className, _methodName);
	 }

	 private void loginUserIfRemembered(ServletRequest req, ServletResponse res) throws ClassNotFoundException, SQLException
	 {
		  String _methodName = "loginUserIfRemembered";

		  TraderLogger.logMethodEntry(_className, _methodName);

		  HttpServletRequest request = (HttpServletRequest) req;
		  HttpServletResponse response = (HttpServletResponse) res;

		  TraderLogger.logInfo(_className, _methodName, "Checking if cookie exists for remember");
		  if (!HttpUtils.wasUserAuthenticationSuccess(request.getSession()))
		  {
			   String uuid = HttpUtils.getCookieValue(request, HttpConsts.COOKIE_USER_LOGIN_REMEMBER_UUID);

			   if (uuid != null)
			   {

				    TraderLogger.logInfo(_className, _methodName, "User cookie found with UUID. Checking if the corresponding record exists in DB: " + uuid);

				    UserLoginHistoryRecord record = userBean.findUserLoginHistoryRecord(uuid);
				    if (record != null)
				    {
						User user = record.getUser();

						HttpUtils.setUserAuthenticated(request.getSession(true), user);
						HttpUtils.addCookie(response, HttpConsts.COOKIE_USER_LOGIN_REMEMBER_UUID, uuid, HttpConsts.MAX_USER_REMEMBER_COOKIE_AGE); // Extends age.

						TraderLogger.logInfo(_className, _methodName, "Record found in DB. Authenticated user " + user.getEmail());

				    }
				    else
				    {
						HttpUtils.removeCookie(response, HttpConsts.COOKIE_USER_LOGIN_REMEMBER_UUID);
						TraderLogger.logInfo(_className, _methodName, "Unable to find the record in DB.  UUID " + uuid);

				    }
			   }
			   else
			   {

				    TraderLogger.logInfo(_className, _methodName, "Cookie for remembering user not found.");
			   }
		  }
		  else
		  {
			   TraderLogger.logInfo(_className, _methodName, "User already logged in");
		  }

		  TraderLogger.logMethodExit(_className, _methodName);
	 }

	 private void doAfterProcessing(ServletRequest request, ServletResponse response) throws IOException, ServletException
	 {
		  // Write code here to process the request and/or response after
		  // the rest of the filter chain is invoked.
		  // For example, a logging filter might log the attributes on the
		  // request object after the request has been processed. 
	/*
		   for (Enumeration en = request.getAttributeNames(); en.hasMoreElements(); ) {
		   String name = (String)en.nextElement();
		   Object value = request.getAttribute(name);
		   log("attribute: " + name + "=" + value.toString());

		   }
		   */
		  // For example, a filter might append something to the response.
	/*
		   PrintWriter respOut = new PrintWriter(response.getWriter());
		   respOut.println("<P><B>This has been appended by an intrusive filter.</B>");
		   */




		  TraderLogger.exiting();
	 }

	 /**
	  *
	  * @param request The servlet request we are processing
	  * @param response The servlet response we are creating
	  * @param chain The filter chain we are processing
	  *
	  * @exception IOException if an input/output error occurs
	  * @exception ServletException if a servlet error occurs
	  */
	 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
	 {

		  String _methodName = "doFilter";
		  TraderLogger.logMethodEntry(_className, _methodName);
		  try
		  {
			   doBeforeProcessing(request, response);
		  }
		  catch (Exception ex)
		  {

			   TraderLogger.logSevere(_className, _methodName, "Unknown exception", ex);
		  }

		  Throwable problem = null;
		  try
		  {
			   chain.doFilter(request, response);
		  }
		  catch (Throwable t)
		  {
			   // If an exception is thrown somewhere down the filter chain,
			   // we still want to execute our after processing, and then
			   // rethrow the problem after that.
			   problem = t;
		  }

		  doAfterProcessing(request, response);

		  // If there was a problem, we want to rethrow it if it is
		  // a known type, otherwise log it.
		  if (problem != null)
		  {
			   if (problem instanceof ServletException)
			   {
				    throw (ServletException) problem;
			   }
			   if (problem instanceof IOException)
			   {
				    throw (IOException) problem;
			   }
			   sendProcessingError(problem, response);
		  }
		  TraderLogger.logMethodExit(_className, _methodName);
	 }

	 /**
	  * Return the filter configuration object for this filter.
	  */
	 public FilterConfig getFilterConfig()
	 {
		  return (this.filterConfig);
	 }

	 /**
	  * Set the filter configuration object for this filter.
	  *
	  * @param filterConfig The filter configuration object
	  */
	 public void setFilterConfig(FilterConfig filterConfig)
	 {
		  this.filterConfig = filterConfig;
	 }

	 /**
	  * Destroy method for this filter
	  */
	 public void destroy()
	 {
	 }

	 /**
	  * Init method for this filter
	  */
	 public void init(FilterConfig filterConfig)
	 {
		  this.filterConfig = filterConfig;
		  if (filterConfig != null)
		  {
		  }
	 }

	 /**
	  * Return a String representation of this object.
	  */
	 @Override
	 public String toString()
	 {
		  if (filterConfig == null)
		  {
			   return ("HttpUserRememberFilter()");
		  }
		  StringBuffer sb = new StringBuffer("HttpUserRememberFilter(");
		  sb.append(filterConfig);
		  sb.append(")");
		  return (sb.toString());
	 }

	 private void sendProcessingError(Throwable t, ServletResponse response)
	 {
		  String _methodName = "sendProcessingError";

		  TraderLogger.logInfo(_className, _methodName, "Unknown exception: " + DebugUtils.getStackTraceAsString(t));
	 }

	 public void log(String msg)
	 {
		  filterConfig.getServletContext().log(msg);
	 }

}
